/*******************************************************************************
 * Copyright (c) 2020 THALES GLOBAL SERVICES.
 *  
 *  This program and the accompanying materials are made available under the
 *  terms of the Eclipse Public License 2.0 which is available at
 *  http://www.eclipse.org/legal/epl-2.0
 *  
 *  SPDX-License-Identifier: EPL-2.0
 *  
 *  Contributors:
 *     Thales - initial API and implementation
 *******************************************************************************/
/*
 * generated by Xtext 2.18.0.M3
 */
package org.polarsys.capella.scenario.editor.dsl.helpers

import org.eclipse.emf.ecore.EObject
import org.polarsys.capella.scenario.editor.helper.EmbeddedEditorInstanceHelper
import org.polarsys.capella.scenario.editor.dsl.textualScenario.SequenceMessage
import org.polarsys.capella.core.model.helpers.CapellaElementExt
import org.eclipse.emf.common.util.EList
import org.polarsys.capella.core.data.fa.ComponentExchange
import org.polarsys.capella.core.data.fa.FunctionalExchange
import org.polarsys.capella.scenario.editor.dsl.textualScenario.CombinedFragment
import org.polarsys.capella.scenario.editor.dsl.textualScenario.Model
import org.polarsys.capella.scenario.editor.dsl.textualScenario.Block
import org.polarsys.capella.scenario.editor.dsl.textualScenario.Element
import java.util.Set
import org.polarsys.capella.scenario.editor.dsl.textualScenario.Message
import org.polarsys.capella.scenario.editor.dsl.textualScenario.FoundMessage
import org.polarsys.capella.scenario.editor.dsl.textualScenario.LostMessage
import java.util.List

/**
 * See https://www.eclipse.org/Xtext/documentation/304_ide_concepts.html#content-assist
 * on how to customize the content assistant.
 */
class TextualScenarioHelper {
	static val TYPE_FE = "FE";
	static val TYPE_CE = "CE";
	/*
	 * calculate the type of exchanges allowed to be declared in the text
	 */
	def static getScenarioAllowedExchangesType(EList<Element> elements) {
		if (EmbeddedEditorInstanceHelper.isESScenario()) {
			if(EmbeddedEditorInstanceHelper.isCEScenario())
				return TYPE_CE
			if(EmbeddedEditorInstanceHelper.isFEScenario())
				return TYPE_FE
			for (element : elements) {
				if (element instanceof Message) {
					var message = element as Message
					return getMessageExchangeType(message)
				}
				if (element instanceof CombinedFragment) {
					var combinedFragment = element as CombinedFragment
					return getScenarioAllowedExchangesType(combinedFragment.block.blockElements)
				}
			}
		}
		return null
	}
	/*
	 * we return CE or FE or null in case we allow both or other type
	 */
	def static getMessageExchangeType(Message message) {
		
		var exchangesAvailable = EmbeddedEditorInstanceHelper.getExchangeMessages(getSourceOfMessage(message),
			getTargetOfMessage(message)
		)
		var allowedTypes = newHashSet as Set<Object>
		for(exchange : exchangesAvailable) {
			if(message.name !== null && message.name.equals(CapellaElementExt.getName(exchange))) {
				var type = getExchangeType(exchange)
				if(type !== null)
					allowedTypes.add(type)
			}
		}
		if(allowedTypes.size() == 1) {
			return allowedTypes.get(0)
		}
		
		return null
	}
	
	/*
	 * we return a list of available exchanges CE or FE
	 */
	def static Set getAllMessageExchangeType(Message message) {
		var allowedTypes = newHashSet as Set<Object>
		var exchangesAvailable = EmbeddedEditorInstanceHelper.getExchangeMessages(getSourceOfMessage(message),
			getTargetOfMessage(message))
		for(exchange : exchangesAvailable) {
			if(message.name !== null && message.name.equals(CapellaElementExt.getName(exchange))) {
				var type = getExchangeType(exchange)
				if(type !== null)
					allowedTypes.add(type)
			}
		}
		
		return allowedTypes
	}
	
	def static getExchangeType(EObject exchangeElement) {
		if (exchangeElement instanceof ComponentExchange)
			return TYPE_CE
		else if (exchangeElement instanceof FunctionalExchange)
			return TYPE_FE
		return null
	}
	
	def private static String getSourceOfMessage(Message message) {
		var source = null as String
		if(message instanceof SequenceMessage) {
			source = (message as SequenceMessage).source
		} else if(message instanceof LostMessage) {
			source = (message as LostMessage).source
		}
		return source
	}
	
	def private static String getTargetOfMessage(Message message) {
		var target = null as String
		if(message instanceof SequenceMessage) {
			target = (message as SequenceMessage).target
		} else if(message instanceof FoundMessage) {
			target = (message as FoundMessage).target
		}
		return target
	}
	
	def static participantsDefinedBefore(Model rootModel) {
		return rootModel.participants
	}
	
	def static participantsDefinedBeforeNames(EObject element) {
		var participantsNames = newArrayList
		var container = getModelContainer(element)
		if (container instanceof Model) {
			var model = container as Model
			var participants = participantsDefinedBefore(model)
			for (participant : participants) {
				participantsNames.add(participant.name)
			}
		}	
		return participantsNames
	}
	
	def static isParticipantKeyword(String keywordValue) {
		var participantsKeywords = EmbeddedEditorInstanceHelper.PARTICIPANT_KEYWORDS;
		return participantsKeywords.contains(keywordValue)
	}
	
	/*
	 * get all elements on the same level as modelContainer  
	 */
	def static getContainerElements(EObject modelContainer) {
		
		if (modelContainer instanceof Model) {
			return (modelContainer as Model).elements
		}
		if (modelContainer instanceof CombinedFragment) {
			var elements = newArrayList
			elements.addAll((modelContainer as CombinedFragment).block.blockElements)
			var operands = (modelContainer as CombinedFragment).operands
			for(operand : operands) {
				elements.addAll(operand.block.blockElements)
			}
			return elements
		}
		
		if (modelContainer instanceof Block) {
			return (modelContainer as Block).blockElements
		}
		return newArrayList
	}
	
	/*
	 * get all elements from xtext
	 */
	def static List<Element> getAllElements(EObject modelContainer, List<Element> allElements) {
		for (Element element : getContainerElements(modelContainer)) {
			if (!(element instanceof CombinedFragment)) {
				allElements.add(element)
			} else {
				allElements.add(element)
				getAllElements(element, allElements)
			}
		}
		return allElements;
	}
	
	/*
	 * get the root model that contains the object given as para
	 */
	def static EObject getModelContainer(EObject object) {
		if(object instanceof Model)
			return object as Model
		if(object !== null)		
			return getModelContainer(object.eContainer)
		return null
	}
	
	/*
	 * get the logic container of an element 
	 * (the container can be the model or a combined fragment)
	 */
	def static EObject getDirectContainer(EObject element) {
		if (element !== null) {
			var container = element.eContainer
			if (container instanceof Model || container instanceof CombinedFragment) {
				return container
			}
			return getDirectContainer(container)

		}
		return null
	}
	
}
